package org.example.kunkun_filter.utils;

import org.example.kunkun_filter.dao.UrlDataResponse;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DouyinDownloaderUtils {

    // 随机User-Agent列表
    private static final String[] USER_AGENTS = {
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15",
            "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
            "Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36",
            "Mozilla/5.0 (iPad; CPU OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
    };

    public static UrlDataResponse extractDownloadUrls(String shareUrl) {
        try {
            // 1. 获取重定向后的真实URL
            String redirectUrl = getRedirectUrl(shareUrl);
            if (redirectUrl == null) {
                System.err.println("无法获取重定向URL: " + shareUrl);
                return null;
            }

            // 2. 获取视频信息页面
            Document doc = fetchHtmlDocument(redirectUrl);
            if (doc == null) {
                System.err.println("无法获取HTML文档: " + redirectUrl);
                return null;
            }

            // 3. 解析视频信息
            return parseVideoInfo(doc);
        } catch (IOException e) {
            System.err.println("处理URL时出错: " + shareUrl);
            e.printStackTrace();
            return null;
        }
    }

    private static String getRedirectUrl(String url) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setInstanceFollowRedirects(false);
        conn.setRequestMethod("GET");
        conn.setRequestProperty("User-Agent", getRandomUserAgent());
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(5000);

        int responseCode = conn.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_MOVED_PERM ||
                responseCode == HttpURLConnection.HTTP_MOVED_TEMP ||
                responseCode == HttpURLConnection.HTTP_SEE_OTHER) {
            String location = conn.getHeaderField("Location");
            if (location != null) {
                // 处理相对路径重定向
                if (location.startsWith("/")) {
                    URL baseUrl = new URL(url);
                    location = baseUrl.getProtocol() + "://" + baseUrl.getHost() + location;
                }
                return location;
            }
        }
        return url;
    }

    private static Document fetchHtmlDocument(String url) throws IOException {
        return Jsoup.connect(url)
                .userAgent(getRandomUserAgent())
                .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
                .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                .header("Connection", "keep-alive")
                .referrer("https://www.douyin.com/")
                .timeout(10000)
                .get();
    }

    private static UrlDataResponse parseVideoInfo(Document doc) {
        // 优先从JSON数据中提取信息
        Elements scriptTags = doc.select("script");
        for (Element script : scriptTags) {
            String scriptContent = script.html();
            if (scriptContent.contains("__INITIAL_STATE__")) {
                Matcher matcher = Pattern.compile("__INITIAL_STATE__\\s*=\\s*(\\{.+?\\})\\s*;").matcher(scriptContent);
                if (matcher.find()) {
                    String jsonData = matcher.group(1);
                    UrlDataResponse jsonResponse = parseFromJson(jsonData);
                    if (jsonResponse != null && !jsonResponse.getDataUrl().isEmpty()) {
                        return jsonResponse;
                    }
                }
            }
        }

        // JSON解析失败时使用HTML解析
        return parseFromHtml(doc);
    }

    private static UrlDataResponse parseFromJson(String jsonData) {
        UrlDataResponse response = new UrlDataResponse();
        Set<String> uniqueUrls = new HashSet<>();
        String title = null;
        String coverUrl = null;
        short type = -1;

        try {
            // 1. 解析标题
            Matcher titleMatcher = Pattern.compile("\"desc\":\"(.*?)\"").matcher(jsonData);
            if (titleMatcher.find()) {
                title = titleMatcher.group(1).replace("\\\"", "\"");
            }

            // 2. 解析封面
            coverUrl = extractCoverUrl(jsonData);

            // 3. 解析内容类型和URL
            // 尝试解析视频
            Matcher videoMatcher = Pattern.compile("\"(?:playAddr|downloadAddr)\"\\s*:\\s*\"(https?://[^\"]+?)\"").matcher(jsonData);
            if (videoMatcher.find()) {
                type = 0;
                String videoUrl = videoMatcher.group(1).replace("\\u002F", "/");
                if (isValidVideoUrl(videoUrl)) {
                    uniqueUrls.add(videoUrl);
                }
            } else {
                // 尝试解析图文
                type = 1;
                Matcher imageMatcher = Pattern.compile("\"url_list\"\\s*:\\s*\\[\"([^\"]+?)\"\\]").matcher(jsonData);
                while (imageMatcher.find()) {
                    String imgUrl = imageMatcher.group(1).replace("\\u002F", "/");
                    if (isContentImage(imgUrl)) {
                        uniqueUrls.add(imgUrl);
                    }
                }
            }

            // 4. 设置响应对象
            if (title == null) {
                title = "抖音内容";
            }
            response.setTitle(title);
            response.setCoverUrl(coverUrl);
            response.setType(type);
            response.setDataUrl(new ArrayList<>(filterUrls(uniqueUrls, type)));
        } catch (Exception e) {
            System.err.println("JSON解析错误: " + e.getMessage());
        }

        return response;
    }

    private static String extractCoverUrl(String jsonData) {
        // 尝试多种封面URL模式
        String[] patterns = {
                "\"cover\":\\{\"url_list\":\\[\"([^\"]+)\"",
                "\"dynamic_cover\":\\{\"url_list\":\\[\"([^\"]+)\"",
                "\"origin_cover\":\\{\"url_list\":\\[\"([^\"]+)\"",
                "\"cover\":\"([^\"]+)\""
        };

        for (String pattern : patterns) {
            Matcher matcher = Pattern.compile(pattern).matcher(jsonData);
            if (matcher.find()) {
                String url = matcher.group(1).replace("\\u002F", "/");
                // 补全相对路径
                if (!url.startsWith("http")) {
                    url = "https://p3.douyinpic.com/" + url;
                }
                return url;
            }
        }
        return null;
    }

    private static UrlDataResponse parseFromHtml(Document doc) {
        UrlDataResponse response = new UrlDataResponse();
        Set<String> uniqueUrls = new HashSet<>();
        String title = doc.title().replace(" - 抖音", "").trim();
        if (title.isEmpty()) title = "抖音内容";

        // 1. 解析封面
        Element coverMeta = doc.selectFirst("meta[property=\"og:image\"]");
        String coverUrl = coverMeta != null ? coverMeta.attr("content") : null;

        // 2. 解析内容类型和URL
        // 尝试查找视频
        Element videoElement = doc.selectFirst("video");
        if (videoElement != null) {
            response.setType((short) 0);
            String videoUrl = videoElement.absUrl("src");
            if (!videoUrl.isEmpty() && isValidVideoUrl(videoUrl)) {
                uniqueUrls.add(videoUrl);
            }
        } else {
            // 尝试查找图文
            response.setType((short) 1);
            // 查找所有可能的图片元素
            Elements imgElements = doc.select("img");
            for (Element img : imgElements) {
                String imgUrl = img.absUrl("src");
                if (!imgUrl.isEmpty() && isContentImage(imgUrl)) {
                    uniqueUrls.add(imgUrl);
                }
            }
        }

        // 3. 设置响应对象
        response.setTitle(title);
        response.setCoverUrl(coverUrl);
        response.setDataUrl(new ArrayList<>(filterUrls(uniqueUrls, response.getType())));

        return response;
    }

    private static boolean isValidVideoUrl(String url) {
        return url != null &&
                (url.contains(".mp4") ||
                        url.contains(".mov") ||
                        url.contains(".m3u8") ||
                        url.contains("/video/"));
    }

    private static boolean isContentImage(String url) {
        return url != null &&
                (url.contains(".jpeg") ||
                        url.contains(".jpg") ||
                        url.contains(".png") ||
                        url.contains(".webp") ||
                        url.contains("/obj/") ||
                        url.contains("/tos-cn-"));
    }

    private static Set<String> filterUrls(Set<String> urls, short type) {
        Set<String> filtered = new HashSet<>();
        for (String url : urls) {
            if (url == null || url.isEmpty()) continue;

            // 类型特定过滤
            if (type == 0 && !isValidVideoUrl(url)) continue;
            if (type == 1 && !isContentImage(url)) continue;

            // 过滤低质量/缩略图
            if (url.contains("_cover") ||
                    url.contains("thumbnail") ||
                    url.contains("icon")) continue;

            // 标准化URL
            String cleanUrl = url.replace("\\u002F", "/")
                    .replace("\\/", "/")
                    .split("\\?")[0]; // 移除查询参数

            filtered.add(cleanUrl);
        }
        return filtered;
    }

    private static String getRandomUserAgent() {
        return USER_AGENTS[(int) (Math.random() * USER_AGENTS.length)];
    }
}